#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <ucontext.h>
#include <sys/mman.h>
#include <math.h>

size_t nmemb;
size_t size;
void *array;
int (*comparator_)(const void *a1, const void *a2);
int i = 0, j = 0;

void f() {
	int a = 1 / 4;
	printf("hello from f\n");
}

void g() {
	int a = 1 / 2;
	printf("hello from g\n");
}


static void sighandler() {
	char *buffer = malloc(size);
	printf("I am sighandler\n");
	for (j = 0; j < nmemb; ++j)
		if (comparator_(array + i*size, array + j*size) > 0) {
			memcpy(buffer, array + i*size, size);
			memcpy(array + i*size, array + j*size, size);
			memcpy(array + j*size, buffer, size);
		}
	free(buffer);
}



void set_signal() {
	struct sigaction sa;
	sa.sa_flags = SA_SIGINFO;
	sigemptyset(&sa.sa_mask);
	sa.sa_sigaction = sighandler;
	
	sigaction(SIGFPE, &sa, NULL);
	sigaction(SIGSEGV, &sa, NULL);
}

int comparator(const void *a1, const void *a2) {
	printf("Comparator called\n");
	
	return (*(const int *)a1 - *(const int *)a2);
}

void sort(void *array_, size_t nmemb_, size_t size_,
	  int (*compar_)(const void*, const void*)){
	nmemb = nmemb_;
	size= size_;
	array = array_;
	comparator_ = compar_;
	printf ("hello from sort\n");
	for (i = 0; i < nmemb; ++i) {
		raise(SIGSEGV);
	}
	printf ("end from sort\n");
}


void sort1(void *array, size_t nmemb, size_t size,
	  int (*compar)(const void*, const void*)){
 	printf("hello from sort1");
	sort(array, nmemb, size, compar);
 	printf("bye-bye from sort1");
}

void sort2(void *array, size_t nmemb, size_t size,
	  int (*compar)(const void*, const void*)){
 	printf("hello from sort2");
	qsort(array, nmemb, size, compar);
 	printf("bye-bue from sort2");
}


int function() {
	int a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
	a = 0;
}

int main(int argc, char **argv) {
	set_signal();
	int array_size = argc - 1;
	int *array = malloc(array_size * sizeof(*array));
	int i = 0;

	for (i = 0; i < array_size; ++i)
		array[i] = atoi(argv[i + 1]);

	int page_size = getpagesize();
	assert (mprotect(sort1 - (unsigned long)sort1 % page_size, page_size, PROT_READ | PROT_WRITE | PROT_EXEC) == 0);
	
	memcpy(sort2, sort1, 35);

	sort2(array, array_size, sizeof(int), comparator);

	for (i = 0; i < array_size; ++i)
		printf("%d ", array[i]);


	free(array);
	/*
	int page_size = getpagesize();
	assert (mprotect(f - (unsigned long)f % page_size, page_size, PROT_READ | PROT_WRITE | PROT_EXEC) == 0);
	int arr[100000] = {};
	sighandler();
	f();
	func arr_p = arr;


//	arr_p();


	int array[10] = {0, 1, 2, 3, 4, 5, 6 ,7, 8, 9};
//	sort(array, 10);
//	qsort(array, 10, sizeof(int), comparator);
	int i = 0;
	for (;i < 10; ++i)
		printf("%d ", array[i]);
*/	
		
	return 0;
}
